
#include "main.h"


static void usb_AddBuf(u8 cmd, u8 dev, u8 dlen, u8 *data);
static void usb_EndOfSend(u8 epnum);
static void usb_GetReport(u8 *buf, u16 len);


#define	usb_BUF_COUNT	64	// 64 * 64 = 4096


static vu32 _vuUsbIsTxCompleted = 1;
static vu32 _vuUsbTxHead = 0;
static vu32 _vuUsbTxTail = 0;
static u8 _abUsbTxBuf[usb_BUF_COUNT][USB_PKT_MAX_LEN] = {0,};

static u32 _bIsUsbOk = 0;


void Usb_Init(void)
{
	USBD_HID_EndOfSend_cb = usb_EndOfSend;
	USBD_HID_GetReport_cb = usb_GetReport;
}

void Usb_PktProc()
{
	if (g_u32BuzzerDelay && (g_vu32SysTickCount > g_u32BuzzerDelay)) {
		g_u32BuzzerDelay = 0;
		Led_Set(eLED_BUZZER, 0);
	}
}


void Usb_PktCmdEvt(u8 cmd, u8 dev, u16 dlen, u8 *data)
{
	if (_bIsUsbOk) {
		if (USB_PKT_DATA_MAX_LEN < dlen) {
			u32 count, i;

			count = dlen / USB_PKT_DATA_MAX_LEN;
			for (i=0; i<count; i++)
				usb_AddBuf(cmd, dev, USB_PKT_DLEN_Make(1, USB_PKT_DATA_MAX_LEN), (data + i*USB_PKT_DATA_MAX_LEN));
			usb_AddBuf(cmd, dev, (dlen % USB_PKT_DATA_MAX_LEN), (data + i*USB_PKT_DATA_MAX_LEN));
		} else {
			usb_AddBuf(cmd, dev, dlen, data);
		}

		if (_vuUsbIsTxCompleted) {
			_vuUsbIsTxCompleted = 0;
			SendReport_Hid(&g_UsbOtgDevice, _abUsbTxBuf[_vuUsbTxTail++], USB_PKT_MAX_LEN);
			if (usb_BUF_COUNT <= _vuUsbTxTail)
				_vuUsbTxTail = 0;
		}
	}
}

void Usb_PktRes(u8 req, u8 dev, u8 cmd, u8 dlen, u8 *data)
{
	if (_bIsUsbOk) {
		u32 uHead = _vuUsbTxHead;

		_abUsbTxBuf[uHead][USB_PKT_POS_RID]	= USB_PKT_REPORT_ID;
		_abUsbTxBuf[uHead][USB_PKT_POS_CMD]	= req;
		_abUsbTxBuf[uHead][USB_PKT_POS_DEV]	= dev;
		_abUsbTxBuf[uHead][USB_PKT_POS_DLEN] = dlen + 1;
		_abUsbTxBuf[uHead][USB_PKT_POS_DATA] = cmd;
		if (dlen)
			memcpy(&_abUsbTxBuf[uHead][USB_PKT_POS_DATA+1], data, dlen);
		if (usb_BUF_COUNT <= ++uHead)
			uHead = 0;

		_vuUsbTxHead = uHead;

		if (_vuUsbIsTxCompleted)
		{
			_vuUsbIsTxCompleted = 0;
			SendReport_Hid(&g_UsbOtgDevice, _abUsbTxBuf[_vuUsbTxTail++], USB_PKT_MAX_LEN);
			if (usb_BUF_COUNT <= _vuUsbTxTail)
				_vuUsbTxTail = 0;
		}
	}
}

static void usb_AddBuf(u8 cmd, u8 dev, u8 dlen, u8 *data)
{
	u32 uHead = _vuUsbTxHead;

	_abUsbTxBuf[uHead][USB_PKT_POS_RID]  = USB_PKT_REPORT_ID;
	_abUsbTxBuf[uHead][USB_PKT_POS_CMD]  = cmd;
	_abUsbTxBuf[uHead][USB_PKT_POS_DEV]  = dev;
	_abUsbTxBuf[uHead][USB_PKT_POS_DLEN] = dlen;
	if (dlen)
		memcpy(&_abUsbTxBuf[uHead][USB_PKT_POS_DATA], data, dlen);
	if (usb_BUF_COUNT <= ++uHead)
		uHead = 0;

	_vuUsbTxHead = uHead;
}

static void usb_EndOfSend(u8 epnum)
{
	u32 uHead = _vuUsbTxHead;

	if (_vuUsbTxTail != uHead) {
		SendReport_Hid(&g_UsbOtgDevice, _abUsbTxBuf[_vuUsbTxTail++], USB_PKT_MAX_LEN);
		if (usb_BUF_COUNT <= _vuUsbTxTail) {
			_vuUsbTxTail = 0;
		}
	} else {
		_vuUsbIsTxCompleted = 1;
	}
}

static void usb_GetReport(u8 *buf, u16 len)
{
	u8 cmd, dev, *pdata, err = ERR_SUCCESS;
	u16 dlen;

	cmd   =  buf[USB_PKT_POS_CMD];
	dev   =  buf[USB_PKT_POS_DEV];
	dlen  =  buf[USB_PKT_POS_DLEN];
	pdata = &buf[USB_PKT_POS_DATA];
	#if	DBG_MSG_USB
	//printf("usb_GetReport(%02X %02X %02X)\r\n", cmd, dev, dlen);
	#endif	//DBG_MSG_USB

	if (0 == _bIsUsbOk) {
		_bIsUsbOk = 1;
	}

	switch (dev) {
	case DEV_TOUCH:
		err = Pkt_CmdProc(eUART_MAX, cmd, dev, &dlen, pdata);
		break;

	case DEV_CAMERA1:
		Uart_PktCmd(eUART_CAM1, cmd, dev, dlen, pdata);
		return;
	case DEV_CAMERA2:
		Uart_PktCmd(eUART_CAM2, cmd, dev, dlen, pdata);
		return;
#if	(CAMERA_MAX_NUM > 2)		
	case DEV_CAMERA3:
		Uart_PktCmd(eUART_CAM3, cmd, dev, dlen, pdata);
		return;
	case DEV_CAMERA4:
		Uart_PktCmd(eUART_CAM4, cmd, dev, dlen, pdata);
		return;
#endif	//CAMERA_MAX_NUM

	default:
		err = ERR_UNKNOWN_DEVICE;
		break;
	}

	if (ERR_SUCCESS == err) {
		Usb_PktRes(CMD_RESULT_SUCCESS, dev, cmd, dlen, pdata);
	} else {
		#if	DBG_MSG_USB
		printf("err(%d) : cmd(%02X) dev(%d) dlen(%02X)\r\n", err, cmd, dev, dlen);
		#endif	//DBG_MSG_USB
		Usb_PktRes(CMD_RESULT_ERROR, dev, cmd, 1, (u8 *)&err);
	}
}

